import os
import json
from typing import List, Dict, Any, Union


class ProgConfig(object):
    def __init__(self):
        self._prog_dir = os.path.abspath('%s/../../prog' % os.path.dirname(os.path.abspath(__file__)))
        self._prog_cfg_path = '%s/cfg.json' % self._prog_dir
        self._cfg_name_map: Dict[str, Any] = {}
        self._cfg_server_name_map: Dict[str, Any] = {}

    def load(self) -> bool:
        if os.path.exists(self._prog_cfg_path):
            json_cfg: List[Dict[str, Any]] = None
            with open(self._prog_cfg_path, 'r') as file:
                json_cfg = json.loads(file.read())

            if json_cfg is not None:
                while len(json_cfg) > 0:
                    item = json_cfg.pop(0)
                    if 'parent' in item:
                        # this item extends from a parent
                        parent = item['parent']
                        if parent not in self._cfg_name_map:
                            # return it to the end of list
                            json_cfg.append(item)
                        else:
                            # copy from parent
                            cfg_item = self._cfg_name_map[parent].copy()

                            # update child info
                            cfg_item['name'] = item['name']
                            cfg_item['server_name'] = item['server_name']
                            self._cfg_name_map[cfg_item['name']] = cfg_item

                            # save server name map
                            for name in cfg_item['server_name']:
                                self._cfg_server_name_map[name] = cfg_item
                    else:
                        # save
                        self._cfg_name_map[item['name']] = item

                        # save server name map
                        for name in item['server_name']:
                            self._cfg_server_name_map[name] = item
                return True
            else:
                return False

    def get_prog_by_name(self, name: str) -> Union[str, None]:
        cfg = self._cfg_name_map[name]
        if cfg is not None:
            return '%s/%s' % (self._prog_dir, cfg['prog'])
        else:
            return None

    def get_prog_by_server_name(self, name: str) -> Union[str, None]:
        cfg = self._cfg_server_name_map[name]
        if cfg is not None:
            return '%s/%s' % (self._prog_dir, cfg['prog'])
        else:
            return None
